﻿using System;
using System.Data.SqlClient;

namespace CoreLibrary.Sql {

    public sealed class SQLUtil {

        public static void Close(SqlConnection connection) {
            if (connection != null) {
                try {
                    connection.Close();
                } catch {
                    //
                }
            }
        }

        public static void Close(SqlDataReader dataReader) {
            if (dataReader != null) {
                try {
                    dataReader.Close();
                } catch {
                    //
                }
            }
        }

        public static T Execute<T>(SqlConnection connection, ISqlQuery<T> query) {
            using (var command = new SqlCommand(query.GetSQL(), connection)) {
                query.SetParameters(command);
                using (var dataReader = command.ExecuteReader()) {
                    return query.GetResult(connection, dataReader);
                }
            }
        }

        public static T Execute<T>(SqlConnection connection, ISqlQuery<T> query, SqlTransaction transaction) {
            using (var command = new SqlCommand(query.GetSQL(), connection)) {
                command.Transaction = transaction;
                query.SetParameters(command);
                using (var dataReader = command.ExecuteReader()) {
                    return query.GetResult(connection, dataReader);
                }
            }
        }

        public static T Execute<T>(SqlConnection connection, ISqlScalar<T> scalar) {
            using (var command = new SqlCommand(scalar.GetSQL(), connection)) {
                scalar.SetParameters(command);
                var result = command.ExecuteScalar();
                return scalar.GetResult(connection, result);
            }
        }

        public static T Execute<T>(SqlConnection connection, ISqlScalar<T> scalar, SqlTransaction transaction) {
            using (var command = new SqlCommand(scalar.GetSQL(), connection)) {
                command.Transaction = transaction;
                scalar.SetParameters(command);
                var result = command.ExecuteScalar();
                return scalar.GetResult(connection, result);
            }
        }

        public static T Execute<T>(SqlConnection connection, ISqlUpdator<T> updator) {
            using (var command = new SqlCommand(updator.GetSQL(), connection)) {
                updator.SetParameters(command);
                var result = command.ExecuteNonQuery();
                return updator.GetResult(connection, result);
            }
        }

        public static T Execute<T>(SqlConnection connection, ISqlUpdator<T> updator, TimeSpan timeout) {
            using (var command = new SqlCommand(updator.GetSQL(), connection)) {
                command.CommandTimeout = (int)timeout.TotalSeconds;
                updator.SetParameters(command);
                var result = command.ExecuteNonQuery();
                return updator.GetResult(connection, result);
            }
        }

        public static T Execute<T>(SqlConnection connection, ISqlUpdator<T> updator, SqlTransaction transaction) {
            using (var command = new SqlCommand(updator.GetSQL(), connection)) {
                command.Transaction = transaction;
                updator.SetParameters(command);
                var result = command.ExecuteNonQuery();
                return updator.GetResult(connection, result);

            }
        }

        public static T ExecuteCommand<T, R>(SqlConnection connection, ISqlCommand<T, R> cmd) {
            if (cmd is ISqlQuery<T>) {
                return Execute(connection, (ISqlQuery<T>)cmd);
            }
            if (cmd is ISqlScalar<T>) {
                return Execute(connection, (ISqlScalar<T>)cmd);
            }
            if (cmd is ISqlUpdator<T>) {
                return Execute(connection, (ISqlUpdator<T>)cmd);
            }
            throw new ArgumentException("Unsupported ISqlCommand type:" + cmd.GetType().FullName);
        }

    }
}